using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using LDNS.SDK.Utilities;
using LDNS.Interfaces;
using LDNS.Models;
using LDNS.Utilities;
using LDNS.Services;
using LDNS.SDK.Commands;
using LDNS.SDK.Commands.Models;
using LDNS.Commands;
using NLog;

namespace LDNS.Services
{
    /// <summary>
    /// 命令执行器：统一处理命令的解析、权限检查和执行
    /// 使用命令处理器工厂管理命令处理器实例
    /// 作者：huobing
    /// </summary>
    public class CommandExecutor
    {
        private readonly IDnsService _dnsService;
        private readonly CommandSource _source;
        private readonly Logger _logger = LogManager.GetCurrentClassLogger();
        
        /// <summary>
        /// 命令处理器缓存字典
        /// 键为命令名称，值为对应的命令处理器实例
        /// </summary>
        private readonly Dictionary<string, ICommandHandler> _handlerCache = new Dictionary<string, ICommandHandler>();

        /// <summary>
        /// 命令来源枚举
        /// </summary>
        public enum CommandSource
        {
            /// <summary>
            /// 控制台命令行
            /// </summary>
            Console,
            /// <summary>
            /// UI界面
            /// </summary>
            UI,
            /// <summary>
            /// Socket连接
            /// </summary>
            Socket
        }
        
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dnsService">DNS服务接口</param>
        /// <param name="source">命令来源</param>
        public CommandExecutor(IDnsService dnsService, CommandSource source)
        {
            _dnsService = dnsService;
            _source = source;
            InitializeHandlers();
        }
        
        /// <summary>
        /// 根据命令名称获取对应的命令处理器
        /// </summary>
        /// <param name="commandName">命令名称</param>
        /// <returns>命令处理器实例，如果找不到返回null</returns>
        public ICommandHandler? GetHandler(string commandName)
        {
            if (_handlerCache.TryGetValue(commandName, out var handler))
            {
                return handler;
            }
            return null;
        }
        
        /// <summary>
        /// 注册命令处理器
        /// </summary>
        /// <param name="handler">命令处理器实例</param>
        public void RegisterHandler(ICommandHandler handler)
        {
            if (!_handlerCache.ContainsKey(handler.CommandName))
            {
                _handlerCache.Add(handler.CommandName, handler);
            }
        }

        
        /// <summary>
        /// 初始化命令处理器实例
        /// </summary>
        private void InitializeHandlers()
        {
            // 注册所有命令处理器
            // 配置相关命令
            RegisterHandler(new GetConfigCommandHandler());
            RegisterHandler(new SetConfigCommandHandler());
                
            // 记录相关命令
            RegisterHandler(new AddCommandHandler());
            RegisterHandler(new RemoveCommandHandler());
            RegisterHandler(new ListRecordsCommandHandler());

            // 上游DNS相关命令
            RegisterHandler(new ListUpstreamCommandHandler());
            RegisterHandler(new SetUpstreamMainDomainCommandHandler());
            // 只有在_dnsService不为null时才注册需要它的命令处理器
            if (_dnsService != null)
            {
                // DNS服务相关命令
                RegisterHandler(new GetStartTimeCommandHandler(_dnsService));
                RegisterHandler(new GetStatisticsCommandHandler(_dnsService));
                RegisterHandler(new GetCacheStatsCommandHandler(_dnsService));
                RegisterHandler(new ClearCacheCommandHandler(_dnsService));
                
                // 服务控制命令
                RegisterHandler(new StatusCommandHandler(_dnsService));
                RegisterHandler(new StartCommandHandler(_dnsService));
                RegisterHandler(new StopCommandHandler(_dnsService));
                RegisterHandler(new RestartCommandHandler(_dnsService));
            }
        }
        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandLine">命令行文本</param>
        /// <param name="result">执行结果</param>
        /// <returns>是否执行成功</returns>
        public bool Execute(string commandLine, out string result)
        {
            try
            {
                // 解析命令
                if (!CommandRegistry.TryResolve(commandLine, out var command, out var args, out var parseError))
                {
                    result = parseError;
                    return false;
                }
                
                if (command == null)
                {
                    result = "命令解析失败：未获得命令实例";
                    return false;
                }
                if (command.Name == HelpCommand.NAME)
                {
                    HelpResult helpResult = ExecuteHelpCommand(args);
                    // 使用统一的JSON工具类序列化helpResult对象，确保按实际类型序列化
                    string serializedResult = JsonUtils.Serialize(helpResult);
                    _logger.Debug($"命令 {command.Name} 执行结果序列化: {serializedResult}");
                    result = "json:"+serializedResult;
                    return true;
                }
                
                // 检查权限
                if (!CheckPermission(command))
                {
                    result = $"权限不足：无法执行命令 {command.Name}";
                    return false;
                }
                
                // 使用命令处理器工厂获取对应的命令处理器
                var handler = GetHandler(command.Name);
                
                if (handler != null)
                {
                    // 使用命令处理器执行命令
                    BaseCommandResult handlerResult = handler.Execute(args, command.Permission);
                    
                    // 使用统一的JSON工具类序列化handlerResult对象，确保按实际类型序列化
                    string serializedResult = JsonUtils.Serialize(handlerResult);
                    _logger.Debug($"命令 {command.Name} 执行结果序列化: {serializedResult}");
                    result = "json:" + serializedResult;
                    return true;
                }
                else
                {
                    result = $"命令 {command.Name} 尚未实现";
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"执行命令时发生错误: {commandLine}");
                result = $"执行命令失败: {ex.Message}";
                return false;
            }
        }

        /// <summary>
        /// 检查权限
        /// </summary>
        /// <param name="command">命令对象</param>
        /// <returns>是否有权限执行</returns>
        private bool CheckPermission(IBaseCommand command)
        {
            // 控制台和UI拥有所有权限
            if (_source == CommandSource.Console || _source == CommandSource.UI)
            {
                return true;
            }
            
            // Socket连接只能执行User权限的命令（主要是记录操作）
            if (_source == CommandSource.Socket)
            {
                return command.Permission == CommandPermission.User;
            }
            
            return false;
        }
        
        /// <summary>
        /// 获取可用命令列表（考虑权限）
        /// </summary>
        /// <returns>可用命令列表</returns>
        public List<IBaseCommand> GetAvailableCommands()
        {
            List<IBaseCommand> availableCommands = [];
            
            foreach (IBaseCommand command in CommandRegistry.Commands)
            {
                if (CheckPermission(command))
                {
                    availableCommands.Add(command);
                }
            }
            
            return availableCommands;
        }
        private HelpResult ExecuteHelpCommand(string[] args)
        {
            if (args.Length > 0)
            {
                // 查找特定命令的帮助
                var commandName = args[0].ToUpperInvariant();
                var command = CommandRegistry.Commands.FirstOrDefault(c => 
                    string.Equals(c.Name, commandName, StringComparison.OrdinalIgnoreCase));
                
                if (command != null)
                {
                    // 调用命令类的GetHelp方法获取帮助信息
                    HelpResult helpResult = BaseCommandResult.CreateSuccessResult<HelpResult>("操作成功", HelpCommand.NAME);
                    helpResult.AddCommandItem(new CommandItem
                    {
                        Name = command.Name,
                        Description = command.Description,
                        Format = command.Format
                    });
                    return helpResult;
                }
                else
                {
                    return BaseCommandResult.CreateErrorResult<HelpResult>($"未知命令: {commandName}", HelpCommand.NAME);
                }
            }
            else
            {
                HelpResult result = BaseCommandResult.CreateSuccessResult<HelpResult>("操作成功", HelpCommand.NAME);
                foreach (var command in GetAvailableCommands())
                {
                    result.AddCommandItem(new CommandItem
                    {
                        Name = command.Name,
                        Description = command.Description
                    });
                }
                return result;
            }
        }

    }
    
}